import datetime
import os
import shutil
import stat
import sys
import time

import paramiko

import LinuxContains

install_fail_dict = {}
install_success_dict = {}
total_hap_num = 0
hap_install_success = 0
hap_install_fail = 0


def exec_cmd(cmd):
    f = os.popen("hdc shell " + "\"" + cmd + "\"")
    text = f.read()
    f.close()
    return text


def exec_cmd_simple(cmd):
    f = os.popen(cmd)
    text = f.read()
    f.close()
    return text


def sftp_download(sftp, local_dir, remote_dir):
    if stat.S_ISDIR(sftp.stat(remote_dir).st_mode):  # 如果sftp服务端的remoterDir是目录，则返回True
        for file in sftp.listdir(remote_dir):
            remote_dir_tmp = os.path.join(remote_dir, file)
            local_dir_tmp = os.path.join(local_dir, file)
            sftp_download(sftp, local_dir_tmp, remote_dir_tmp)
    else:
        print("download file:", remote_dir)
        try:
            sftp.get(remote_dir, local_dir)
        except Exception as e:
            print('download exception:', e)


def sftp_from_remote(local_path, log_path):
    host = LinuxContains.HOST  # sftp主机
    port = LinuxContains.PORT  # 端口
    username = LinuxContains.USERNAME  # sftp用户名
    password = LinuxContains.PASSWD
    local_dir = local_path
    local_log_path = log_path
    remote_dir = LinuxContains.SIGN_HAP_DIR
    remote_dir_full = LinuxContains.FULL_SIGN_HAP_DIR

    remote_log = LinuxContains.ERROR_LOG_PATH
    remote_log_full = LinuxContains.FULL_ERROR_LOG_PATH

    print("download start")
    sf = paramiko.Transport((host, port))
    sf.connect(username=username, password=password)
    sftp = paramiko.SFTPClient.from_transport(sf)
    sftp_download(sftp, local_dir, remote_dir)
    sftp_download(sftp, local_dir, remote_dir_full)
    sftp_download(sftp, local_log_path, remote_log)
    sftp_download(sftp, local_log_path, remote_log_full)
    sf.close()
    print("download stop\n")


def get_haps(local_dir):
    files = os.listdir(local_dir)
    hap_list = []
    for file in files:
        if "_signed.hap" in file:
            hap_list.append(file)
    return hap_list


def install_hap(local_hap, hap_path):
    global hap_install_success, hap_install_fail
    for hap in local_hap:
        print("install " + hap_path + "\\" + hap)
        install_res = exec_cmd_simple("hdc install -r {}".format(hap_path + "\\" + hap))
        if not install_res.__contains__("msg:install bundle successfully."):
            install_res = install_res.replace("\nAppMod finish\n\n", "")
            install_fail_dict[hap] = install_res
            hap_install_fail = hap_install_fail + 1
        else:
            install_success_dict[hap] = install_res
            hap_install_success = hap_install_success + 1
    time.sleep(3)


def uninstall_hap(begin_bundles):
    end_bundles = get_all_bundles()
    uninstall_bundles = list(set(end_bundles) - set(begin_bundles))
    for bundle in uninstall_bundles:
        print("uninstall " + bundle)
        uninstall_res = exec_cmd_simple("hdc uninstall {}".format(bundle))
    time.sleep(3)


def clear_dir(dir_path):
    if os.path.exists(dir_path):
        shutil.rmtree(dir_path)
    os.makedirs(dir_path)


def clear_file(file_path):
    if os.path.exists(file_path):
        os.remove(file_path)
    os.system(r"type nul>{}".format(file_path))


def get_all_bundles():
    bundles = exec_cmd("bm dump -a")
    bundles = bundles.splitlines()
    del bundles[0]
    return bundles


def batch_install(haps, base_dir):
    limit = 10
    count = 0
    cur_batch_hap = []
    begin_bundles = get_all_bundles()
    for hap in haps:
        cur_batch_hap.append(hap)
        count = count + 1
        if count == limit:
            install_hap(cur_batch_hap, "{0}\\SampleSignHap".format(base_dir))
            uninstall_hap(begin_bundles)
            count = 0
            cur_batch_hap.clear()
    if len(cur_batch_hap) != 0:
        install_hap(cur_batch_hap, "{0}\\SampleSignHap".format(base_dir))
        uninstall_hap(begin_bundles)
        cur_batch_hap.clear()


def writelog(base_dir):
    install_fail_path = "{0}\\install-fail.log".format(base_dir)
    clear_file(install_fail_path)
    error_log = open(install_fail_path, mode='w')
    for i in install_fail_dict:
        error_log.write('{0} : {1}'.format(i, install_fail_dict[i]))
    error_log.write('项目数量 : {0}'.format(total_hap_num))
    error_log.write('成功数量 : {0}'.format(hap_install_success))
    error_log.write('失败数量 : {0}'.format(hap_install_fail))
    error_log.flush()
    error_log.close()


def init_out():
    base_dir = sys.path[0]
    out_path = "{0}\\install_out\\{1}".format(base_dir, datetime.datetime.now().strftime('%Y%m%d'))
    clear_dir(out_path)
    clear_dir("{0}\\errorLog".format(out_path))
    clear_dir("{0}\\SampleSignHap".format(out_path))
    clear_file("{0}\\install-fail.log".format(out_path))
    return out_path


if __name__ == '__main__':
    out_base = init_out()
    sftp_from_remote("{0}\\SampleSignHap".format(out_base), "{0}\\errorLog".format(out_base))
    haps = get_haps("{0}\\SampleSignHap".format(out_base))
    total_hap_num = len(haps)
    batch_install(haps, out_base)
    writelog(out_base)
